"""信号分析工具函数模块.

包含置信度计算、指标名称标准化和指标值提取等工具函数。
"""

from __future__ import annotations

from typing import Any, Dict, Tuple

import numpy as np
import pandas as pd

from .types import SignalStrength


def calculate_confidence(
    value: float,
    threshold_lower: float,
    threshold_upper: float,
    is_oversold: bool = True,
) -> Tuple[float, SignalStrength]:
    """根据偏离阈值的程度计算置信度和强度.
    
    置信度计算规则：
    - 强烈信号：指标值明显偏离阈值（如RSI < 20 或 > 80），置信度 0.7-1.0
    - 中等信号：指标值接近阈值（如RSI 25-30 或 70-75），置信度 0.5-0.7
    - 轻微信号：指标值在阈值附近（如RSI 30-35 或 65-70），置信度 0.3-0.5
    
    Parameters
    ----------
    value : float
        指标当前值
    threshold_lower : float
        下阈值（超卖阈值或低位阈值）
    threshold_upper : float
        上阈值（超买阈值或高位阈值）
    is_oversold : bool, default True
        是否为超卖超买类指标（True表示值越小越看多，False表示值越大越看多）
        
    Returns
    -------
    Tuple[float, SignalStrength]
        置信度和信号强度的元组
    """
    if pd.isna(value) or np.isnan(value):
        return 0.0, SignalStrength.WEAK
    
    # 计算到阈值的距离（归一化）
    if is_oversold:
        # 超卖超买类指标：值越小越看多，值越大越看空
        if value < threshold_lower:
            # 超卖区域：计算偏离下阈值的程度
            distance = (threshold_lower - value) / (threshold_lower + 1e-6)
            if distance > 0.5:  # 明显超卖（如RSI < 15）
                return min(0.9, 0.5 + distance * 0.4), SignalStrength.STRONG
            elif distance > 0.2:  # 接近超卖（如RSI 20-25）
                return 0.5 + distance * 0.4, SignalStrength.MODERATE
            else:  # 轻微超卖（如RSI 25-30）
                return 0.3 + distance * 0.4, SignalStrength.WEAK
        elif value > threshold_upper:
            # 超买区域：计算偏离上阈值的程度
            distance = (value - threshold_upper) / (100 - threshold_upper + 1e-6)
            if distance > 0.5:  # 明显超买（如RSI > 85）
                return min(0.9, 0.5 + distance * 0.4), SignalStrength.STRONG
            elif distance > 0.2:  # 接近超买（如RSI 75-80）
                return 0.5 + distance * 0.4, SignalStrength.MODERATE
            else:  # 轻微超买（如RSI 70-75）
                return 0.3 + distance * 0.4, SignalStrength.WEAK
        else:
            # 中性区域
            return 0.2, SignalStrength.WEAK
    else:
        # 位置类指标：值越大越看多，值越小越看空
        if value < threshold_lower:
            # 低位区域
            distance = (threshold_lower - value) / (threshold_lower + 1e-6)
            if distance > 0.5:
                return min(0.9, 0.5 + distance * 0.4), SignalStrength.STRONG
            elif distance > 0.2:
                return 0.5 + distance * 0.4, SignalStrength.MODERATE
            else:
                return 0.3 + distance * 0.4, SignalStrength.WEAK
        elif value > threshold_upper:
            # 高位区域
            distance = (value - threshold_upper) / (100 - threshold_upper + 1e-6)
            if distance > 0.5:
                return min(0.9, 0.5 + distance * 0.4), SignalStrength.STRONG
            elif distance > 0.2:
                return 0.5 + distance * 0.4, SignalStrength.MODERATE
            else:
                return 0.3 + distance * 0.4, SignalStrength.WEAK
        else:
            # 中性区域
            return 0.2, SignalStrength.WEAK


def normalize_indicator_name(name: str) -> str:
    """标准化指标名称（处理不同命名格式）.
    
    例如："rsi_14" -> "rsi", "macd_dif" -> "macd"
    
    Parameters
    ----------
    name : str
        原始指标名称
        
    Returns
    -------
    str
        标准化后的指标名称
    """
    name_lower = name.lower()
    
    # RSI相关
    if "rsi" in name_lower:
        return "rsi"
    
    # MACD相关
    if "macd" in name_lower:
        return "macd"
    
    # KDJ相关
    if "kdj" in name_lower:
        return "kdj"
    
    # CMO相关
    if "cmo" in name_lower:
        return "cmo"
    
    # CCI相关
    if "cci" in name_lower:
        return "cci"
    
    # MFI相关
    if "mfi" in name_lower:
        return "mfi"
    
    # Williams %R相关
    if "williams_r" in name_lower or "williams" in name_lower:
        return "williams_r"
    
    # 布林带相关
    if "bb_" in name_lower or "bollinger" in name_lower:
        return "bollinger"
    
    # ADX相关
    if "adx" in name_lower:
        return "adx"
    
    # OBV相关
    if "obv" in name_lower:
        return "obv"
    
    # VWAP相关
    if "vwap" in name_lower:
        return "vwap"
    
    # 价格百分位相关
    if "price_percentile" in name_lower:
        return "price_percentile"
    
    # 均线相关
    if "sma_" in name_lower or "ema_" in name_lower:
        return "ma_system"
    
    # 趋势持续性相关
    if "trend_persistence" in name_lower:
        return "trend_persistence"
    
    # K线形态相关
    if "pattern_" in name_lower:
        return "candlestick_patterns"
    
    return name_lower


def extract_indicator_values(features: pd.DataFrame, latest_only: bool = True) -> Dict[str, Any]:
    """从特征DataFrame中提取指标值.
    
    Parameters
    ----------
    features : pd.DataFrame
        特征DataFrame
    latest_only : bool, default True
        是否只提取最新一行的值
        
    Returns
    -------
    Dict[str, Any]
        指标值字典，key为指标名称，value为指标值
    """
    if latest_only:
        # 只提取最新一行
        row = features.iloc[-1]
    else:
        # 提取所有行（返回字典的字典）
        return {idx: extract_indicator_values(features.loc[[idx]], latest_only=True) for idx in features.index}
    
    values = {}
    
    # 提取各个指标值
    for col in features.columns:
        if pd.notna(row[col]):
            values[col] = row[col]
    
    return values

